import os
import sys
import time
import logging
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import threading
import uvicorn
import locale

class CloudPrintService(win32serviceutil.ServiceFramework):
    _svc_name_ = "CloudPrintService"
    _svc_display_name_ = "云打印系统服务"
    _svc_description_ = "提供云打印系统的后端服务，包括文件上传、打印队列管理和打印功能"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.is_running = False
        self.server = None
        self.server_thread = None
        
        # 设置工作目录为脚本所在目录
        if getattr(sys, 'frozen', False):
            # 如果是打包后的可执行文件
            self.base_dir = os.path.dirname(sys.executable)
        else:
            # 如果是脚本运行
            self.base_dir = os.path.dirname(os.path.abspath(__file__))
        
        os.chdir(self.base_dir)
        
        # 设置日志
        log_dir = os.path.join(self.base_dir, "logs")
        os.makedirs(log_dir, exist_ok=True)
        
        # 配置系统编码
        if sys.platform == 'win32':
            # 设置控制台编码为UTF-8
            try:
                locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')
            except:
                try:
                    locale.setlocale(locale.LC_ALL, 'Chinese_China.936')
                except:
                    pass
        
        # 确保日志文件使用UTF-8编码
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(os.path.join(log_dir, "service.log"), encoding='utf-8'),
                logging.StreamHandler()
            ]
        )
        self.logger = logging.getLogger('CloudPrintService')
        self.logger.info(f'服务初始化，工作目录: {self.base_dir}')
    
    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.is_running = False
        self.logger.info('服务停止中...')
    
    def SvcDoRun(self):
        servicemanager.LogMsg(
            servicemanager.EVENTLOG_INFORMATION_TYPE,
            servicemanager.PYS_SERVICE_STARTED,
            (self._svc_name_, '')
        )
        self.is_running = True
        self.logger.info('服务启动中...')
        
        # 确保必要的目录存在
        os.makedirs(os.path.join(self.base_dir, "print_status"), exist_ok=True)
        os.makedirs(os.path.join(self.base_dir, "static"), exist_ok=True)
        os.makedirs(os.path.join(self.base_dir, "watch_folder"), exist_ok=True)
        
        # 在新线程中启动FastAPI服务
        self.server_thread = threading.Thread(target=self.run_server)
        self.server_thread.daemon = True
        self.server_thread.start()
        
        # 等待服务停止信号
        while self.is_running:
            if win32event.WaitForSingleObject(self.hWaitStop, 1000) == win32event.WAIT_OBJECT_0:
                break
            
    def run_server(self):
        try:
            # 导入应用但不直接运行它
            from app import app
            
            # 读取配置
            import configparser
            port = 8000
            host = "0.0.0.0"
            log_level = "info"
            
            try:
                config = configparser.ConfigParser()
                config_path = os.path.join(self.base_dir, 'config.ini')
                if os.path.exists(config_path):
                    self.logger.info(f'读取配置文件: {config_path}')
                    config.read(config_path, encoding='utf-8')
                    
                    if 'Server' in config:
                        port = config.getint('Server', 'port', fallback=8000)
                        host = config.get('Server', 'host', fallback="0.0.0.0")
                        
                    if 'Logging' in config:
                        log_level = config.get('Logging', 'level', fallback="info").lower()
                else:
                    self.logger.warning(f'配置文件不存在: {config_path}，使用默认配置')
            except Exception as e:
                self.logger.error(f'读取配置文件失败: {str(e)}')
            
            self.logger.info(f'启动FastAPI服务器 {host}:{port}')
            
            # 创建日志目录
            log_dir = os.path.join(self.base_dir, "logs")
            os.makedirs(log_dir, exist_ok=True)
            
            # 创建配置
            config = uvicorn.Config(
                app=app, 
                host=host, 
                port=port, 
                log_level=log_level,
                log_config={
                    "version": 1,
                    "disable_existing_loggers": False,
                    "formatters": {
                        "default": {
                            "()": "uvicorn.logging.DefaultFormatter",
                            "fmt": "%(asctime)s - %(levelname)s - %(message)s",
                            "use_colors": False,
                        },
                    },
                    "handlers": {
                        "default": {
                            "formatter": "default",
                            "class": "logging.StreamHandler",
                            "stream": "ext://sys.stderr",
                        },
                        "file": {
                            "formatter": "default",
                            "class": "logging.FileHandler",
                            "filename": os.path.join(log_dir, "uvicorn.log"),
                            "encoding": "utf-8",
                        },
                    },
                    "loggers": {
                        "uvicorn": {"handlers": ["default", "file"], "level": "INFO"},
                        "uvicorn.error": {"level": "INFO"},
                        "uvicorn.access": {"handlers": ["default", "file"], "level": "INFO", "propagate": False},
                    },
                }
            )
            
            # 创建服务器
            self.server = uvicorn.Server(config)
            
            # 启动服务器
            self.server.run()
        except Exception as e:
            self.logger.error(f'启动FastAPI服务器时发生错误: {str(e)}')
            servicemanager.LogErrorMsg(f"Error: {str(e)}")

def print_help():
    """打印帮助信息"""
    print("云打印系统服务管理工具")
    print("用法:")
    print("  cloud_print_service.exe [命令]")
    print("命令:")
    print("  install    - 安装服务")
    print("  remove     - 卸载服务")
    print("  start      - 启动服务")
    print("  stop       - 停止服务")
    print("  restart    - 重启服务")
    print("  debug      - 调试模式运行")
    print("  help       - 显示此帮助信息")
    print("注意: 安装和卸载服务需要管理员权限")

def main():
    # 如果是打包后的可执行文件，确保工作目录正确
    if getattr(sys, 'frozen', False):
        base_dir = os.path.dirname(sys.executable)
        os.chdir(base_dir)
        
        # 确保日志目录存在
        log_dir = os.path.join(base_dir, "logs")
        os.makedirs(log_dir, exist_ok=True)
    
    if len(sys.argv) == 1:
        # 无参数启动，作为服务运行
        try:
            servicemanager.Initialize()
            servicemanager.PrepareToHostSingle(CloudPrintService)
            servicemanager.StartServiceCtrlDispatcher()
        except Exception as e:
            print(f"作为服务启动失败: {str(e)}")
            print("尝试使用 'python app.py' 命令直接启动应用")
            sys.exit(1)
    else:
        cmd = sys.argv[1].lower() if len(sys.argv) > 1 else ""
        
        if cmd == "help" or cmd == "--help" or cmd == "-h":
            print_help()
        elif cmd == "debug":
            # 调试模式，直接运行app.py
            print("以调试模式启动应用...")
            try:
                from app import app
                import uvicorn
                uvicorn.run(app, host="0.0.0.0", port=8000)
            except Exception as e:
                print(f"以调试模式启动失败: {str(e)}")
                sys.exit(1)
        else:
            # 其他命令交给win32serviceutil处理
            try:
                win32serviceutil.HandleCommandLine(CloudPrintService)
            except Exception as e:
                print(f"服务操作失败: {str(e)}")
                print("请确保以管理员权限运行此命令")
                sys.exit(1)

if __name__ == '__main__':
    main() 